page.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import { Metadata } from 'next';
  2. import { notFound } from 'next/navigation';
  3. import { allDocs } from 'contentlayer/generated';
  4. import { name } from '@/config/site';
  5. import { getTableOfContents } from '@/lib/toc';
  6. import Mdx from '@/components/MDX';
  7. import TablerSponsorsBanner from '@/components/TablerSponsorsBanner';
  8. import Link from 'next/link';
  9. import TOC from '@/components/TOC';
  10. import DocsMenu from '@/components/DocsMenu';
  11. import Icon from '@/components/Icon';
  12. import Ad from '@/components/Ad';
  13. interface DocPageProps {
  14. params: {
  15. slug: string[]
  16. }
  17. }
  18. async function getDocFromParams(params) {
  19. const slug = params.slug?.join('/') || '';
  20. const doc = allDocs.find((doc) => doc.slugAsParams === slug);
  21. if (!doc) {
  22. null;
  23. }
  24. return doc;
  25. }
  26. export async function generateMetadata({
  27. params,
  28. }: DocPageProps): Promise<Metadata> {
  29. const doc = await getDocFromParams(params);
  30. if (!doc) {
  31. return {};
  32. }
  33. return {
  34. title: `${doc.title} - Documentation - ${name}`,
  35. description: doc.description,
  36. openGraph: {
  37. type: 'article',
  38. },
  39. };
  40. }
  41. export async function generateStaticParams(): Promise<
  42. DocPageProps['params'][]
  43. > {
  44. return allDocs.map((doc) => ({
  45. slug: doc.slugAsParams.split('/'),
  46. }));
  47. }
  48. export default async function DocPage({ params }: DocPageProps) {
  49. const doc = await getDocFromParams(params);
  50. if (!doc) {
  51. notFound();
  52. }
  53. const toc = await getTableOfContents(doc.body.raw);
  54. return (
  55. <div className="row g-0">
  56. <div className="md:col-auto docs-side">
  57. {/*<input type="search" className="form-control w-100 mb-5" placeholder="Search&hellip;" />*/}
  58. <DocsMenu />
  59. </div>
  60. <div className="col">
  61. <div className="row">
  62. <div className="md:col">
  63. <div className="py-6 md:pl-6">
  64. <nav aria-label="breadcrumbs" className="breadcrumb mb-6">
  65. <ul className="breadcrumb-list">
  66. <li className="breadcrumb-item">
  67. <Link href="/" className="breadcrumb-link">
  68. Home
  69. </Link>
  70. </li>
  71. <li className="breadcrumb-item">
  72. <Link href="/docs" className="breadcrumb-link">
  73. Documentation
  74. </Link>
  75. </li>
  76. <li className="breadcrumb-item">
  77. <Link href={`/docs/${params.slug.join('/')}`} className="breadcrumb-link">
  78. {doc.title}
  79. </Link>
  80. </li>
  81. </ul>
  82. </nav>
  83. <div className="markdown">
  84. {/* {category && (
  85. <div className="h-subheader text-primary">{category}</div>
  86. )} */}
  87. {doc.title && <h1>{doc.title}</h1>}
  88. {doc.description && <p className="lead">{doc.description}</p>}
  89. <Mdx code={doc.body.code} />
  90. </div>
  91. </div>
  92. </div>
  93. <div className="docs-side-toc">
  94. <div className="pl-6 font-h6 pt-6">
  95. <div className="h6 mb-3">On this page</div>
  96. <div>
  97. <TOC toc={toc} />
  98. </div>
  99. <div className="mt-4 border-top pt-4">
  100. <a href={`https://github.com/tabler/tabler/blob/main/docs/${doc.slugAsParams.split(',').join('/')}.mdx`} className="link-muted">
  101. Improve this page
  102. <Icon name="edit" className="icon-inline ml-2" />
  103. </a>
  104. </div>
  105. <div className="mt-5">
  106. <Ad />
  107. </div>
  108. </div>
  109. </div>
  110. <div className="col-12">
  111. <div className="pl-6 mt-7">
  112. <TablerSponsorsBanner />
  113. </div>
  114. </div>
  115. </div>
  116. </div>
  117. </div>
  118. );
  119. }